package com.example.computer_exam_training_sys.service.impl;

import com.example.computer_exam_training_sys.entity.UserAnalysisInfo;
import com.example.computer_exam_training_sys.entity.UserPractice;
import com.example.computer_exam_training_sys.entity.KnowledgePointInfo;
import com.example.computer_exam_training_sys.mapper.UserAnalysisMapper;
import com.example.computer_exam_training_sys.mapper.UserPracticeMapper;
import com.example.computer_exam_training_sys.mapper.UserPracticeDetailMapper;
import com.example.computer_exam_training_sys.mapper.KnowledgePointMapper;
import com.example.computer_exam_training_sys.service.UserAnalysisService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.*;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.stream.Collectors;
import org.json.JSONObject;
import org.json.JSONArray;

@Service
public class UserAnalysisServiceImpl implements UserAnalysisService {

    @Autowired
    private UserAnalysisMapper mapper;
    
    @Autowired
    private UserPracticeMapper practiceMapper;
    
    @Autowired
    private UserPracticeDetailMapper practiceDetailMapper;
    
    @Autowired
    private KnowledgePointMapper knowledgePointMapper;

    @Override
    public List<UserAnalysisInfo> findAll() {
        return mapper.findAll();
    }

    @Override
    public List<UserAnalysisInfo> findByUserId(Integer userId) {
        return mapper.findByUserId(userId);
    }

    @Override
    public UserAnalysisInfo findById(Integer id) {
        return mapper.findById(id);
    }

    @Override
    public int insert(UserAnalysisInfo info) {
        return mapper.insert(info);
    }

    @Override
    public int update(UserAnalysisInfo info) {
        return mapper.update(info);
    }

    @Override
    public int deleteById(Integer id) {
        return mapper.deleteById(id);
    }
    
    @Override
    public UserAnalysisInfo generateUserAnalysis(Integer userId, Integer courseId, String startDateStr, String endDateStr) {
        UserAnalysisInfo analysisInfo = new UserAnalysisInfo();
        analysisInfo.setUserId(userId);
        analysisInfo.setCourseId(courseId);
        
        try {
            // 解析日期
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
            Date startDate = dateFormat.parse(startDateStr);
            Date endDate = dateFormat.parse(endDateStr);
            
            analysisInfo.setPracticeRangeStart(startDate);
            analysisInfo.setPracticeRangeEnd(endDate);
            
            // 获取指定时间范围内的练习记录
            List<UserPractice> practices = practiceMapper.selectByUserId(userId).stream()
                .filter(p -> p.getCourseId().equals(courseId))
                .filter(p -> {
                    Date practiceDate = p.getStartTime();
                    return !practiceDate.before(startDate) && !practiceDate.after(endDate);
                })
                .collect(Collectors.toList());
            
            // 计算总题目数和正确题目数
            int totalQuestions = 0;
            int correctQuestions = 0;
            
            // 统计每个知识点的错题数量，用于分析薄弱点
            Map<Integer, Integer> pointErrorCounts = new HashMap<>();
            
            // 按日期统计做题量，用于生成学习趋势
            Map<String, Integer> dailyQuestionCounts = new HashMap<>();
            
            SimpleDateFormat trendDateFormat = new SimpleDateFormat("yyyy-MM-dd");
            
            for (UserPractice practice : practices) {
                // 累计题目数量
                totalQuestions += practice.getQuestionCount();
                correctQuestions += practice.getCorrectCount();
                
                // 记录知识点错题
                if (practice.getPointId() != null) {
                    int wrongCount = practice.getQuestionCount() - practice.getCorrectCount();
                    pointErrorCounts.put(practice.getPointId(), 
                            pointErrorCounts.getOrDefault(practice.getPointId(), 0) + wrongCount);
                }
                
                // 记录每日做题量
                String dateKey = trendDateFormat.format(practice.getStartTime());
                dailyQuestionCounts.put(dateKey, 
                        dailyQuestionCounts.getOrDefault(dateKey, 0) + practice.getQuestionCount());
            }
            
            // 设置总题目数和正确题目数
            analysisInfo.setTotalQuestions(totalQuestions);
            analysisInfo.setCorrectQuestions(correctQuestions);
            
            // 计算正确率
            double accuracyRate = totalQuestions > 0 ? (double) correctQuestions / totalQuestions : 0;
            analysisInfo.setAccuracyRate(accuracyRate);
            
            // 生成薄弱知识点JSON
            JSONArray weakPointsArray = new JSONArray();
            
            // 获取错题最多的3个知识点
            pointErrorCounts.entrySet().stream()
                .sorted(Map.Entry.<Integer, Integer>comparingByValue().reversed())
                .limit(3)
                .forEach(entry -> {
                    Integer pointId = entry.getKey();
                    KnowledgePointInfo point = knowledgePointMapper.findById(pointId);
                    if (point != null) {
                        JSONObject weakPoint = new JSONObject();
                        weakPoint.put("pointId", pointId);
                        weakPoint.put("pointName", point.getPointName());
                        weakPoint.put("errorCount", entry.getValue());
                        weakPointsArray.put(weakPoint);
                    }
                });
            
            analysisInfo.setWeakPoints(weakPointsArray.toString());
            
            // 生成学习趋势JSON
            JSONObject studyTrendObj = new JSONObject();
            
            // 按日期排序
            List<String> sortedDates = new ArrayList<>(dailyQuestionCounts.keySet());
            Collections.sort(sortedDates);
            
            for (String date : sortedDates) {
                studyTrendObj.put(date, dailyQuestionCounts.get(date));
            }
            
            analysisInfo.setStudyTrend(studyTrendObj.toString());
            
        } catch (Exception e) {
            e.printStackTrace();
        }
        
        return analysisInfo;
    }
    
    @Override
    public int saveOrUpdateUserAnalysis(Integer userId, Integer courseId) {
        // 默认分析最近30天的数据
        LocalDate endDate = LocalDate.now();
        LocalDate startDate = endDate.minusDays(30);
        
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        String startDateStr = startDate.format(formatter);
        String endDateStr = endDate.format(formatter);
        
        // 生成分析数据
        UserAnalysisInfo analysisInfo = generateUserAnalysis(userId, courseId, startDateStr, endDateStr);
        
        // 查找是否已有该用户该课程的分析数据
        List<UserAnalysisInfo> existingAnalyses = mapper.findByUserId(userId).stream()
            .filter(a -> a.getCourseId().equals(courseId))
            .collect(Collectors.toList());
        
        if (!existingAnalyses.isEmpty()) {
            // 更新现有记录
            analysisInfo.setId(existingAnalyses.get(0).getId());
            return mapper.update(analysisInfo);
        } else {
            // 创建新记录
            return mapper.insert(analysisInfo);
        }
    }
    
    @Override
    public int refreshAnalysis(Integer analysisId) {
        // 获取现有分析记录
        UserAnalysisInfo existingAnalysis = mapper.findById(analysisId);
        
        if (existingAnalysis == null) {
            return 0;  // 记录不存在
        }
        
        // 使用现有的日期范围重新生成分析数据
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        String startDateStr = dateFormat.format(existingAnalysis.getPracticeRangeStart());
        String endDateStr = dateFormat.format(existingAnalysis.getPracticeRangeEnd());
        
        // 生成新的分析数据
        UserAnalysisInfo newAnalysis = generateUserAnalysis(
                existingAnalysis.getUserId(),
                existingAnalysis.getCourseId(),
                startDateStr,
                endDateStr
        );
        
        // 设置ID以更新现有记录
        newAnalysis.setId(analysisId);
        
        // 更新记录
        return mapper.update(newAnalysis);
    }
    
    @Override
    public List<Integer> getUserCourseIds(Integer userId) {
        // 从用户练习记录中获取用户参与的所有课程ID
        List<UserPractice> userPractices = practiceMapper.selectByUserId(userId);
        
        // 提取不重复的课程ID
        return userPractices.stream()
                .map(UserPractice::getCourseId)
                .distinct()
                .collect(Collectors.toList());
    }
    
    @Override
    public List<UserAnalysisInfo> analyzeAllUserCourses(Integer userId) {
        // 获取用户的所有课程ID
        List<Integer> courseIds = getUserCourseIds(userId);
        
        // 存储所有课程的分析结果
        List<UserAnalysisInfo> allAnalyses = new ArrayList<>();
        
        // 为每个课程生成或更新分析数据
        for (Integer courseId : courseIds) {
            // 保存或更新分析数据
            int result = saveOrUpdateUserAnalysis(userId, courseId);
            
            if (result > 0) {
                // 查找更新后的分析数据
                List<UserAnalysisInfo> analyses = mapper.findByUserId(userId).stream()
                    .filter(a -> a.getCourseId().equals(courseId))
                    .collect(Collectors.toList());
                
                if (!analyses.isEmpty()) {
                    allAnalyses.add(analyses.get(0));
                }
            }
        }
        
        return allAnalyses;
    }
    
    @Override
    public Map<String, Object> getUserOverallAnalysis(Integer userId) {
        Map<String, Object> result = new HashMap<>();
        
        // 获取用户所有课程的分析数据
        List<UserAnalysisInfo> allAnalyses = analyzeAllUserCourses(userId);
        
        if (allAnalyses.isEmpty()) {
            // 如果没有分析数据，返回默认值
            result.put("totalQuestions", 0);
            result.put("totalCorrectQuestions", 0);
            result.put("averageAccuracyRate", 0.0);
            result.put("courseCount", 0);
            return result;
        }
        
        // 计算总题目数和总正确题目数
        int totalQuestions = 0;
        int totalCorrectQuestions = 0;
        
        for (UserAnalysisInfo analysis : allAnalyses) {
            totalQuestions += analysis.getTotalQuestions() != null ? analysis.getTotalQuestions() : 0;
            totalCorrectQuestions += analysis.getCorrectQuestions() != null ? analysis.getCorrectQuestions() : 0;
        }
        
        // 计算平均正确率
        double averageAccuracyRate = totalQuestions > 0 ? (double) totalCorrectQuestions / totalQuestions : 0;
        
        // 设置结果
        result.put("totalQuestions", totalQuestions);
        result.put("totalCorrectQuestions", totalCorrectQuestions);
        result.put("averageAccuracyRate", averageAccuracyRate);
        result.put("courseCount", allAnalyses.size());
        
        return result;
    }
    
    @Override
    public String getCombinedWeakPoints(Integer userId) {
        // 获取用户所有课程的分析数据
        List<UserAnalysisInfo> allAnalyses = analyzeAllUserCourses(userId);
        
        if (allAnalyses.isEmpty()) {
            // 如果没有分析数据，返回空数组
            return new JSONArray().toString();
        }
        
        // 用于存储所有知识点的错误次数
        Map<Integer, WeakPointInfo> combinedWeakPoints = new HashMap<>();
        
        // 遍历每个课程的分析数据，提取薄弱知识点
        for (UserAnalysisInfo analysis : allAnalyses) {
            String weakPointsStr = analysis.getWeakPoints();
            if (weakPointsStr != null && !weakPointsStr.isEmpty()) {
                try {
                    JSONArray weakPointsArray = new JSONArray(weakPointsStr);
                    
                    // 遍历每个薄弱知识点
                    for (int i = 0; i < weakPointsArray.length(); i++) {
                        JSONObject weakPoint = weakPointsArray.getJSONObject(i);
                        Integer pointId = weakPoint.getInt("pointId");
                        String pointName = weakPoint.getString("pointName");
                        int errorCount = weakPoint.getInt("errorCount");
                        
                        // 更新组合的薄弱知识点
                        if (combinedWeakPoints.containsKey(pointId)) {
                            WeakPointInfo info = combinedWeakPoints.get(pointId);
                            info.errorCount += errorCount;
                        } else {
                            WeakPointInfo info = new WeakPointInfo();
                            info.pointId = pointId;
                            info.pointName = pointName;
                            info.errorCount = errorCount;
                            combinedWeakPoints.put(pointId, info);
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        
        // 生成组合的薄弱知识点JSON
        JSONArray resultArray = new JSONArray();
        
        // 按错误次数排序，获取错误最多的前5个知识点
        combinedWeakPoints.values().stream()
            .sorted((a, b) -> Integer.compare(b.errorCount, a.errorCount))
            .limit(5)
            .forEach(info -> {
                JSONObject obj = new JSONObject();
                obj.put("pointId", info.pointId);
                obj.put("pointName", info.pointName);
                obj.put("errorCount", info.errorCount);
                resultArray.put(obj);
            });
        
        return resultArray.toString();
    }
    
    // 内部类，用于存储薄弱知识点信息
    private static class WeakPointInfo {
        Integer pointId;
        String pointName;
        int errorCount;
    }
}
